from multiprocessing import Process,Lock,Queue
from threading import Thread

'''进程间通信（IPC）-跟系统内核关联大
文件：通过访问文件进行多进程通信,可能会出现读写冲突，加互斥锁解决my_lock = Lock()
套接字（sokect）：通过一个协议，连接两个进程，主要通过网络请求。比如进程1上传文件到云盘，进程2从云盘下载文件
管道：用文件的内存缓冲区作为管道，实现进程间通信。匿名管道：主进程和子进程进行交互，具名管道：不同进程可以进行交互
消息队列（queue）:一个存在内核内存空间中的列表,,redis就是消息队列+socket
共享内存(了解)：进程访问内核态同一块内存
信号量(了解)：不是用来传递数据的, 是用来传递消息，进程B要等到进程A执行到某一步操作后, 才会启动，进程A->发消息->内核->转发信息->进程B
'''
#文件
def process_save_to_file(index,my_lock):
    with my_lock:
        with open('5.2.log','a',encoding='utf-8') as f:
            f.write(f'\"{str(index)}\":{index},\n')

#消息队列
def process_save_to_queue(index,my_queue):
    my_queue.put(index)


'''线程间通信--进程可以进行的通信，线程都可以完成。线程间通信强调的是线程之间传递对象引用
共享变量：线程安全问题：线程有GIL锁, 但是拿到GIL锁不代表可以一直执行下去.现代计算机多线程也是A执行一会儿, B执行一会儿这样交替执行.
解决线程安全：将重要指令包装成原子操作(不可分割的)，如加互斥锁lock = Lock()
'''

#进行大量运算，以便让线程间互相争夺锁
a = 0
thread_lock = Lock()
def thread_shared_variables():
    global a
    for i in range(10**6):
        #如果不加锁，最后输出的a可能不等于0
        with thread_lock:
            a += 1
            a -= 1

if __name__ == '__main__':
    #进程Process改成线程Thread即可进行线程间的通信
    for i in range(10):
        my_lock = Lock()
        p = Process(target=process_save_to_file,args=(i,my_lock))
        p.start()
        p.join()
    print('---process_save_to_file is ok---')

    #进程Process改成线程Thread即可进行线程间的通信
    my_queue = Queue()
    process_queue_arr = []
    for i in range(10):
        p = Process(target=process_save_to_queue,args=(i,my_queue))
        process_queue_arr.append(p)
        p.start()
        p.join()
    for i in process_queue_arr:
        print(my_queue.get(),':',i)
    print('---process_save_to_queue is ok---')

    thread_arr = []
    for i in range(3):
        t = Thread(target=thread_shared_variables)
        thread_arr.append(t)
        t.start()
    for i in thread_arr:
        t.join()
    print(a)
    print('---thread_shared_variables is ok---')